import {
  Injectable,
  InternalServerErrorException,
  NotFoundException,
  ForbiddenException,
} from '@nestjs/common';
import { UpdateArticleDto } from './dto/update-article.dto';
import { PrismaService } from 'src/services/prisma.service';
import { articles } from '@prisma/client';
import { QueryArticleInfo, UserInfo } from 'src/typing';

@Injectable()
export class ArticlesService {
  constructor(private readonly prisma: PrismaService) {}
  async createArticle(userInfo: UserInfo, otherInfo): Promise<articles> {
    try {
      return this.prisma.articles.create({
        data: {
          ...otherInfo,
          username: userInfo.username,
          author: { connect: { user_id: userInfo.user_id } },
        },
      });
    } catch (error) {
      throw new InternalServerErrorException('创建失败');
    }
  }

  async updateArticle(
    article_id: number,
    updateArticle: UpdateArticleDto,
  ): Promise<any> {
    try {
      return this.prisma.articles.update({
        where: {
          article_id,
        },
        data: updateArticle,
      });
    } catch (error) {
      throw new InternalServerErrorException('编辑失败');
    }
  }

  async getSelfArticle(article_id: number): Promise<articles | null> {
    const article = await this.prisma.articles.findUnique({
      where: {
        article_id,
      },
    });
    if (!article) {
      throw new NotFoundException('文章不存在');
    }
    return article;
  }

  async getSelfArticles({
    user_id,
    page = 1,
    pageSize = 10,
    keywords = '',
    top_up,
    popular,
    type,
    original,
    page_view,
    words_num,
    comment_num,
    create_time,
    update_time,
  }: QueryArticleInfo): Promise<[articles[], number]> {
    const createTimeStartUTC =
      create_time && new Date(`${create_time}T00:00:00.000Z`);
    const createTimeEndUTC =
      create_time && new Date(`${create_time}T23:59:59.999Z`);
    const updateTimeStartUTC =
      update_time && new Date(`${update_time}T00:00:00.000Z`);
    const updateTimeEndUTC =
      update_time && new Date(`${update_time}T23:59:59.999Z`);
    const where = {
      user_id,
      ...(keywords && {
        OR: ['title', 'content', 'username', 'synopsis'].map((field) => ({
          [field]: { contains: keywords },
        })),
      }),
      ...(top_up !== undefined && top_up !== null && { top_up }),
      ...(popular !== undefined && popular !== null && { popular }),
      ...(original !== undefined && original !== null && { original }),
      ...(type !== undefined && type !== null && { type }),
      ...(page_view !== undefined &&
        page_view !== null && {
          page_view: {
            gte: page_view,
          },
        }),
      ...(words_num !== undefined &&
        words_num !== null && {
          words_num: {
            gte: words_num,
          },
        }),
      ...(comment_num !== undefined &&
        comment_num !== null && {
          comment_num: {
            gte: comment_num,
          },
        }),
      // 筛选 create_time update_time
      ...(create_time !== '' &&
        create_time !== undefined &&
        create_time !== null && {
          create_time: {
            gt: createTimeStartUTC,
            lt: createTimeEndUTC,
          },
        }),
      ...(update_time !== '' &&
        update_time !== undefined &&
        update_time !== null && {
          update_time: {
            gt: updateTimeStartUTC,
            lt: updateTimeEndUTC,
          },
        }),
    };

    const [list, total] = await Promise.all([
      this.prisma.articles.findMany({
        // 跳过记录数
        skip: (page - 1) * pageSize,
        // 返回记录数
        take: pageSize,
        where,
        // 排序
        orderBy: [
          { top_up: 'desc' },
          { popular: 'desc' },
          { create_time: 'desc' },
        ],
      }),
      this.prisma.articles.count({
        where,
      }),
    ]);
    return [list, total];
  }

  async reOneArticle(article_id: number) {
    try {
      await this.prisma.articles.delete({
        where: {
          article_id,
        },
      });
    } catch (error) {
      throw new InternalServerErrorException('删除失败');
    }
  }

  async identifyAuth(user_id: number, article_id: number): Promise<void> {
    const article = await this.getSelfArticle(article_id);
    if (article?.user_id !== user_id) {
      throw new ForbiddenException('无该文章相关权限');
    }
  }

  async getSimpleArticleInfo({ page, pageSize, keywords }) {
    const where = { title: { contains: keywords } };
    return await Promise.all([
      this.prisma.articles.findMany({
        skip: (page - 1) * pageSize,
        take: pageSize,
        where,
        select: {
          article_id: true,
          title: true,
        },
        orderBy: { create_time: 'desc' },
      }),
      this.prisma.articles.count({ where }),
    ]);
  }
}
